#include "state.hpp"

#include "qbe/src/ecs/app.hpp"
#include "qbe/src/ecs/bus.hpp"
#include "qbe/src/input/input.hpp"

#include "qbe/src/editing/mirror/mirror.hpp"
#include "qbe/src/editing/quick_align/quick_align.hpp"
#include "qbe/src/editing/rotation/rotation.hpp"
#include "qbe/src/editing/slice/slice.hpp"

#include "qbe/src/ui_message/layerMessage.h"

#include "qbe/src/tools/setting_interface.h"

#include "qbe/src/select/select.hpp"

#include "qbe/src/undoRedo/undoRedo.hpp"

#include "qbe/src/select/select_cmd.hpp"

#include "qbe/src/editing/delete/delete.hpp"

#include "qbe/src/editing/copy/copy.hpp"

#include <windows.h>

namespace qbe::state {

State* state;

void update(ecs::Query query, ecs::Bus& bus) {
  static bool first_set = true;
  auto& state = query.get_resource<State>();

  qbe::UiMessage::UiEnableState& enable_event = query.get_resource<qbe::UiMessage::UiEnableState>();

  // if (state.getDrawingMode() == state::DrawingModeType::None && state.getEditingMode() == state::EditingModeType::None &&
  //     state.getSelectMode() == state::SelectModeType::None) {
  //   state.switchMode(state::SelectModeType::Overall);
  // }

  {
    auto cell = query.get_resource<qlib::Cell::s_ptr>();
    auto& reg = cell->reg;

    bool have_select_obj = false;
    bool is_ref = false;
    int num = 0;
    auto view = reg.view<select::SelectTag>();

    view.each([&have_select_obj, &num, &is_ref, &reg](entt::entity e) {
      have_select_obj = true;
      if (reg.try_get<qlib::Reference::s_ptr>(e)) {
        is_ref = true;
      }

      num++;
    });

    enable_event.have_select_obj = have_select_obj;
    enable_event.select_any_two_obj = num >= 2;
    enable_event.select_one_obj = num == 1;
    enable_event.select_one_ref = num == 1 && is_ref;
    enable_event.select_array_copy = have_select_obj;
    enable_event.select_no3d_any_obj = have_select_obj;

    auto& handModule = query.get_resource<vsg::ref_ptr<input::HandleBundle>>();
    if (handModule->mousePressed(vsg::ButtonMask::BUTTON_MASK_3) && have_select_obj) {
      qbe::UiMessage::MouseRightMenu event;
      event.open = true;
      POINT p;
      GetCursorPos(&p);  // 直接获取屏幕坐标
      event.pos = qlib::Vec2d(p.x, p.y);
      bus.send(event);
    }

    if (handModule->mousePressed(vsg::BUTTON_MASK_1)) {
      qbe::UiMessage::MouseRightMenu event;
      event.open = false;
      bus.send(event);
    }
  }

  if (first_set) {
    auto& models = query.get_resource<qbe::tools::SettingInterfaceObjcet>();
    auto info = models.getDisplaySettingsInfo();

    state.setAdsorption(info.adsorption_enable_adsorption);
    state.setAbsorbPrecision(info.drawing_board_adsorption_accuracy);

    first_set = false;
  }

  auto switchModeEvents = bus.receive<SwitchModeEvent>();
  auto saveExitEvents = bus.receive<SaveExitModeEvent>();
  auto exitEvents = bus.receive<ExitModeEvent>();

  if (!switchModeEvents.empty()) {
    // bus.send<qbe::UiMessage::OperatorInfoMessage>(qbe::UiMessage::OperatorInfoMessage{""});  //清空状态栏
    auto mode = switchModeEvents.back().mode;

    if (state::isModeType<state::DrawingModeType>(mode)) {
      state.switchMode(mode, false);
    }

    if (state::isModeType<state::SelectModeType>(mode)) {
      state.switchMode(mode, false);
    }

    if (state::isModeType<state::EditingModeType>(mode)) {
      auto editing_mode = state::getModeType<state::EditingModeType>(mode);

      if (editing_mode == state::EditingModeType::Rotation) {
        auto& models = query.get_resource<qbe::rotation::Models>();
        if (switchModeEvents.back().rotateInfo == 0) {
          models.state = qbe::rotation::State::Clockwise90;
        } else if (switchModeEvents.back().rotateInfo == 1) {
          models.state = qbe::rotation::State::NoClockwise90;
        } else if (switchModeEvents.back().rotateInfo == 2) {
          models.state = qbe::rotation::State::AngleRotation;
        } else if (switchModeEvents.back().rotateInfo == 3) {
          models.state = qbe::rotation::State::ManualRotation;
        }
        state.switchMode(mode, true);
      } else if (editing_mode == state::EditingModeType::QuickAlign) {
        auto& models = query.get_resource<qbe::quickAlign::Param>();

        if (state.getEditingMode() == state::EditingModeType::QuickAlign) {
          bool isPointAlign = switchModeEvents.back().quickAling_isPoint;
          auto& quickAlignModels = query.get_resource<qbe::quickAlign::Param>();
          if (quickAlignModels.isPointAlign != isPointAlign) {
            quickAlignModels.need_change = true;
          }
        } else {
          models.isPointAlign = switchModeEvents.back().quickAling_isPoint;
          if (switchModeEvents.back().use_default_quick_align) {
            models.use_default_quick_align = true;
            models.isPointAlign = models.last_is_point;
          }
          state.switchMode(mode, true);
        }

      } else if (editing_mode == state::EditingModeType::Mirror) {
        auto& models = query.get_resource<qbe::mirror::Models>();
        models.isXMirror = switchModeEvents.back().mirrorIsX;
        state.switchMode(mode, true);
      } else if (editing_mode == state::EditingModeType::Slice) {
        if (enable_event.select_region_cutting_obj) {
          auto& models = query.get_resource<qbe::slice::Models>();
          models.isXSlice = switchModeEvents.back().sliceIsX;
          state.switchMode(mode, true);
        }
      } else if (editing_mode == state::EditingModeType::Extension) {
        state.switchMode(mode, true);
      } else if (editing_mode == state::EditingModeType::Stretch) {
        state.switchMode(mode, true);
        state.switchMode(state::SelectModeType::Part);
      } else {
        state.switchMode(mode, true);
      }
    }
  }

  auto angleBevel_e = bus.receive<AngleBevel>();
  if (!angleBevel_e.empty()) {
    // state.setAngleTheAdsorption(angleBevel_e.back().value);
    state.setAngleTheAdsorption(angleBevel_e.back().value);
  }

  auto angleLock_e = bus.receive<AngleLock>();
  if (!angleLock_e.empty()) {
    state.setAngleLocking(angleLock_e.back().value);
  }

  auto absorb_e = bus.receive<Absorb>();
  if (!absorb_e.empty()) {
    state.setAdsorption(absorb_e.back().value);

    if (absorb_e.back().value) {
      state.setAbsorbPrecision(absorb_e.back().precision);
    }
  }

  auto switchLayer = bus.receive<UiMessage::ChangeLayer>();
  if (!switchLayer.empty()) {
    bool haveLayer = switchLayer.back().have_use_layer;
    uint32_t layer = switchLayer.back().change_to_layer;

    if (haveLayer) {
      state.setCurrentLayer(layer);
    } else {
      state.exit();
    }

    state.setCurrentLayer(haveLayer);
  }

  auto setManualAngle = bus.receive<SetManualAngle>();
  if (!setManualAngle.empty()) {
    auto& rotation_models = query.get_resource<rotation::Models>();
    rotation_models.setManualAngle(query);
  }

  auto setDelete = bus.receive<SetDelete>();
  if (!setDelete.empty()) {
    dele::deleteSelectObj(query, bus);
  }

  auto setCopy = bus.receive<SetCopy>();
  if (!setCopy.empty()) {
    copy::SetCopy(query);
  }

  auto setAffix = bus.receive<SetAffix>();
  if (!setAffix.empty()) {
    copy::SetCopy(query);
    state.switchMode(state::EditingModeType::Affix);
  }

  // if (!saveExitEvents.empty()) {
  //   state.saveExit();
  // }

  // if (!exitEvents.empty()) {
  //   state.exit();
  // }
}

template <typename T, typename... Args>
int getSelectObjNum_impl(entt::registry& reg) {
  int res = 0;

  auto view = reg.view<select::SelectTag>();
  view.each([&res, &reg](entt::entity e) {
    if (reg.try_get<T>(e)) {
      res++;
    }
  });

  if constexpr (sizeof...(Args) > 0) {
    res += getSelectObjNum_impl<Args...>(reg);
  }

  return res;
}

template <typename T, typename... Args>
int getMergeSelectObjNum_imple(entt::registry& reg) {
  int res = 0;

  auto view = reg.view<select::SelectTag>();
  view.each([&res, &reg](entt::entity e) {
    if (reg.try_get<T>(e)) {
      if constexpr (std::is_same_v<T, qlib::Path::s_ptr>) {
        qlib::Path::s_ptr path = reg.get<T>(e);
        if (path->width > 0) {
          res++;
        }
      } else {
        res++;
      }
    }
  });

  if constexpr (sizeof...(Args) > 0) {
    res += getSelectObjNum_impl<Args...>(reg);
  }

  return res;
}

void send(ecs::Query query, ecs::Bus& bus) {
  auto cell = query.get_resource<qlib::Cell::s_ptr>();
  auto& reg = cell->reg;

  auto& state = query.get_resource<State>();

  CurrentModeEvent current_event;
  current_event.drawingMode = state.getDrawingMode();
  current_event.editingMode = state.getEditingMode();
  current_event.selectMode = state.getSelectMode();
  bus.send(current_event);

  qbe::UiMessage::UiEnableState& enable_event = query.get_resource<qbe::UiMessage::UiEnableState>();

  auto& select_cmd = query.get_resource<select::SelectCmd>();
  auto& axis = query.get_resource<axis::Axis>();

  bool havePartObj = !select_cmd.select_parts().empty();

  // 整体与部分选择
  {
    enable_event.is_whole_selected_graph = (state.getSelectMode() == state::SelectModeType::Overall);
    enable_event.is_part_selected_grpah = havePartObj;
  }

  // 是否有选择对象，选中对象数量
  {
    bool have_select_obj = false;
    bool have_select_array_obj = false;
    int num = 0;
    bool is_ref = false;
    auto view = reg.view<select::SelectTag>();

    view.each([&have_select_obj, &num, &reg, &have_select_array_obj, &is_ref](entt::entity e) {
      have_select_obj = true;
      num++;
      if (reg.try_get<qlib::Reference::s_ptr>(e)) {
        is_ref = true;
      }
      if (reg.try_get<qlib::ViewArea3D::s_ptr>(e) || reg.try_get<qlib::SectionArea3D::s_ptr>(e)) {

      } else {
        have_select_array_obj = true;
      }
    });

    enable_event.have_select_obj = have_select_obj;
    enable_event.select_any_two_obj = num >= 2;
    enable_event.select_one_obj = num == 1;
    enable_event.select_one_ref = num == 1 && is_ref;
    enable_event.select_array_copy = have_select_array_obj;
    enable_event.select_no3d_any_obj = have_select_obj;
  }

  // 选中合并对象数量
  {
    enable_event.select_merge_obj =
        getMergeSelectObjNum_imple<qlib::Path::s_ptr, qlib::Rectangle::s_ptr, qlib::Polygon::s_ptr, qlib::Ellipse::s_ptr, qlib::Fan::s_ptr>(reg) >= 2;
  }

  // 切割对象
  {
    enable_event.select_region_cutting_obj =
        getSelectObjNum_impl<qlib::Path::s_ptr, qlib::Rectangle::s_ptr, qlib::Polygon::s_ptr, qlib::Ellipse::s_ptr, qlib::Fan::s_ptr>(reg) >= 1;
  }
  // 选中至少一个引用对象
  { enable_event.select_least_one_obj = getSelectObjNum_impl<qlib::Reference::s_ptr>(reg) >= 1; }
  enable_event.selct_boolean_obj = enable_event.select_merge_obj;
  // 是否有可粘贴对象
  {
    bool have_part_obj = false;
    auto& selectModels = query.get_resource<select::SelectPartModel>();

    if (selectModels.selects.size() > 0) {
      have_part_obj = true;
    }

    enable_event.have_paste_obj = true;
  }

  // 是否可撤销恢复
  {
    auto& undoredo_module = query.get_resource<undoRedoT::UndoRedoModule>();
    undoredo_module.switchCell(cell);
    undoRedoT::CommandManager* comm = undoRedoT::CommandManager::Instance();

    enable_event.redo_enable = comm->CanRedo();
    enable_event.undo_enable = comm->CanUndo();
  }

  bus.send(enable_event);
}

void StateManager::build(ecs::App& app) {
  ecs::Query query = ecs::Query(app);
  ecs::Bus& bus = app.get_bus();

  State state(query, bus);
  app.insert_resource(state);

  qbe::UiMessage::UiEnableState enable_event;
  app.insert_resource(enable_event);

  app.add_stage<UpdateStage>();
  app.add_stage<LastStage>();

  app.add_systems<UpdateStage>(update);
  app.add_systems<LastStage>(send);
}

}  // namespace qbe::state